<template>
    <!-- 添加spu或者修改spu -->
    <div>
        <!-- model是收集数据 -->
        <el-form ref="form" label-width="80px" :model="spu">
            <el-form-item label="SPU名称">
                <el-input placeholder="SPU名称" v-model="spu.spuName"></el-input>
            </el-form-item>

            <el-form-item label="品牌">
                <!-- value 是收集数据，收集到哪里 -->
                <el-select placeholder="请选择品牌" v-model="spu.tmId">
                    <el-option :label="tm.tmName" :value="tm.id" v-for="(tm,index) in tradeMarkList" :key="tm.id"></el-option>
                </el-select>
            </el-form-item>

            <el-form-item label="SPU描述">
                <el-input type="textarea" placeholder="SPU描述" rows="5" v-model="spu.description"></el-input>
            </el-form-item>

            <el-form-item label="SPU图片">
                <!-- 上传图片，action：图片上传的地址， list-type：文件列表的类型（此处是照片墙），
                    file-list：上传的文件列表，由于照片墙显示的图片需要数组，数组里面的元素需要有name和url字段
                    on-preview：图片预览的时候触发， on-remove：图片删除的时候触发
                    on-success 上传成功的钩子
                -->
                <el-upload
                    action="/dev-api/admin/product/fileUpload"
                    list-type="picture-card"
                    :file-list="spuImageList"
                    :on-success="upLoadSuccess"
                    :on-preview="handlePictureCardPreview"
                    :on-remove="handleRemove">
                    <i class="el-icon-plus"></i>
                </el-upload>
                <el-dialog :visible.sync="dialogVisible">
                    <img width="100%" :src="dialogImageUrl" alt="">
                </el-dialog>
            </el-form-item>

            <el-form-item label="销售属性">
                <!-- 把未选择的销售属性用value收集到saleValueId中 -->
                <el-select :placeholder="`还有${unSelectSaleAttr.length}项销售属性未选择`" v-model="saleAttrIdAndName" >
                    <el-option :label="unSale.name" :value="`${unSale.id}:${unSale.name}`" v-for="(unSale,index) in unSelectSaleAttr" :key="unSale.id"></el-option>
                </el-select>
                <el-button type="primary" icon="el-icon-plus" :disabled="addSaleAttrButton" @click="addSaleAttr">添加销售属性</el-button>
                <el-table style="width: 100%" border :data="spu.spuSaleAttrList">
                    <el-table-column type="index" label="序号" width="80" align="center"></el-table-column>
                    <el-table-column prop="saleAttrName" label="属性名" width="180"></el-table-column>
                    <el-table-column prop="saleAttrName.spuSaleAttrValueList" label="属性值名称列表">
                        <template slot-scope="{row,$index}">
                            <!-- el-tag :用户展示已有属性值列表的数据 -->
                            <el-tag
                                :key="tag.id"
                                v-for="(tag,index) in row.spuSaleAttrValueList"
                                closable
                                :disable-transitions="false"
                                @close="handleClose(row,index)"
                            >
                                {{tag.saleAttrValueName}}
                            </el-tag>
                            <el-input class="input-new-tag" v-if="row.inputVisible" v-model="row.inputValue" ref="saveTagInput" size="small"
                                      @keyup.enter.native="handleInputConfirm(row)"
                                      @blur="handleInputConfirm(row)"
                            >
                                11111111111
                            </el-input>
                            <el-button v-else class="button-new-tag" size="small" @click="addSaleAttrValue(row)">添加</el-button>
                        </template>
                    </el-table-column>
                    <el-table-column prop="address" label="操作" width="80" align="center">
                        <template slot-scope="{row,$index}">
                            <el-button type="danger" icon="el-icon-delete" size="mini" @click="deleteSaleAttr(row,$index)"></el-button>
                        </template>
                    </el-table-column>
                </el-table>
            </el-form-item>

            <el-form-item>
                <el-button type="primary" @click="addOrUpdateSpu">保存</el-button>
                <!-- 点击取消，让父组件中的scene为0 自定义事件 -->
                <el-button @click="quXiao">取消</el-button>
            </el-form-item>
        </el-form>
    </div>
</template>

<script>
export default {
    name: "SpuForm",
    data() {
        return {
            dialogImageUrl: '',
            dialogVisible: false,
            // 存储spu信息
            spu: {
                category3Id:0,      // 三级分类的id
                tmId:'',             // 品牌id
                description:'',     // spu描述
                spuName:'',         // spu名称
                // 收集spu图片的信息
                spuImageList:[
                    /*{
                        id:0,
                        imgName:'',
                        imgUrl:'',
                        spuId:0
                    }*/
                ],
                // 平台属性与属性值
                spuSaleAttrList:[
                    {
                        /*baseSaleAttrId:0,
                        id:0,
                        saleAttrName:'',
                        spuId:0,
                        spuSaleAttrValueList:[
                            /!*{
                                baseSaleAttrId:0,
                                id:0,
                                isChecked:'',
                                saleAttrName:'',
                                saleAttrValueName:'',
                                spuId:0
                            }*!/
                        ]*/
                    }
                ]
            },
            // 品牌信息
            tradeMarkList: [],
            // 存储spu图片数据
            spuImageList:[],
            // 平台销售属性(项目的全部属性)
            spuBaseSaleAttrList:[],
            // 收集未选择的销售属性id
            saleAttrIdAndName:[],
        }
    },
    props: ['scene'],
    methods: {
        // 照片墙删除某一个图片的时候会触发
        handleRemove(file, fileList) {
            // file 是删除的那一张图片
            // fileList 是删除图片之后，剩余的其他图片，将来发送服务器的时候，是需要它的
            // console.log(file, fileList);
            // 将删除后剩余的图片保存到组件中
            this.spuImageList = fileList
            // 对于已有的图片，是有name、url字段的，因为照片墙展示数据的时候必须有这两个属性，对于服务器而言是不需要name、url字段的，将来在提交数据的时候需要处理
        },
        // 照片墙预览功能
        handlePictureCardPreview(file) {
            // 将图片地址赋值给 dialogImageUrl
            this.dialogImageUrl = file.url;
            // 预览对话框显示
            this.dialogVisible = true;
        },
        // 图片上传成功时触发
        upLoadSuccess(response, file, fileList) {
            // response 服务器返回的信息，有 code、message、data，其中data中有上传的图片在服务器中的url地址
            // file 是上传的这张图片的信息
            // fileList 是上传之后所有的图片的信息，是一个数组
            // console.log(response, file, fileList)
            // 收集图片的信息
            this.spuImageList = fileList
        },
        // 取消按钮。添加或修改SPU，取消按钮，点击即可回到展示数据列表
        quXiao() {
            // 取消按钮的回调，通知父亲切换场景为 0
            this.$emit('changeSpuFormScene', {scene:0,flag:''})
            // 清除数据
            // console.log(this._data)
            // console.log(this.$options.data())
            // Object.assign(this._data,this.$options.data())  // 这样写会报错
            // 解释：
            // Object.assign() 是ES6中新增的方法，可以合并对象
            // 组件实例 this._data，可以操作data当中响应式数据
            // this.$options可以获取配置对象，配置对象的data函数执行，返回的响应式数据为空
            // 清除数据，每次点击添加按钮，要把之前添加的数据清除
            this.spu =  {
                category3Id:0,      // 三级分类的id
                tmId:'',             // 品牌id
                description:'',     // spu描述
                spuName:'',         // spu名称
                // 收集spu图片的信息
                spuImageList:[],
                // 平台属性与属性值
                spuSaleAttrList:[]
            }
            // 上次收集的图片也置空
            this.spuImageList = []
        },
        // 修改Spu时获取数据    子组件写方法，子组件身上打一个ref，父组件通过 $refs 获取到子组件，也就是说能获取到子组件身上的方法
        async getSpuData(row) {
            // row 是父组件传过来的，代表是选中的某一条数据
            // console.log('发请求',row)
            // 获取spu信息
            let sDResult = await this.$API.spu.reqSpu(row.id)
            // console.log(sDResult)
            if (sDResult.code == 200) {
                this.spu = sDResult.data
            } else {
                this.$message.error('获取Spu信息失败！')
            }

            // 获取品牌信息
            let sTMLResult = await this.$API.spu.reqSpuTradeMarkList()
            // console.log(sTMLResult)
            if (sTMLResult.code == 200) {
                this.tradeMarkList = sTMLResult.data
            } else {
                this.$message.error('获取品牌信息失败!')
            }

            // 获取spu图片
            let sILResult = await this.$API.spu.reqSpuImageList(row.id)
            // console.log('获取spu图片结果',sILResult)
            if (sILResult.code == 200) {
                // 由于照片墙显示的图片需要数组，数组里面的元素需要有name和url字段
                // 因此需要把服务器返回的数据进行修改
                let listArr = sILResult.data
                // console.log(sILResult.data)
                listArr.forEach(item => {
                    // console.log(item)        // 每一条图片数据
                    item.name =item.imgName
                    item.url = item.imgUrl
                })
                // 把整理好的数据赋值给 spuImageList
                this.spuImageList = listArr
            } else {
                this.$message.error('获取spu图片失败！')
            }

            // 获取平台全部销售属性
            let bSALResult = await this.$API.spu.reqBaseSaleAttrList()
            // console.log(bSALResult)
            if (bSALResult.code == 200) {
                this.spuBaseSaleAttrList = bSALResult.data
            } else {
                this.$message.error('获取平台销售属性失败！')
            }
        },
        // 添加新的销售属性
        addSaleAttr() {
            // console.log(this.saleAttrIdAndName)     // 2:版本      2是id，版本是名称
            // 因为收集到的数据是 2:版本 这种格式，所以要进行切割
            const baseSaleAttrId = this.saleAttrIdAndName.split(':')[0]      // id
            const saleAttrName = this.saleAttrIdAndName.split(':')[1]        // 属性名称
            let addSaleAttrObject = {baseSaleAttrId,saleAttrName,spuSaleAttrValueList:[]}
            // 添加新的销售属性
            this.spu.spuSaleAttrList.push(addSaleAttrObject)
            // 清空数据
            this.saleAttrIdAndName = ''
        },
        // 删除销售属性值，点击叉号删除该销售属性值
        handleClose(row,index) {
            row.spuSaleAttrValueList.splice(index,1)
        },
        // 添加新的销售属性值
        addSaleAttrValue(row) {
            // 点击销售属性值当中的添加按钮时，需要有button变为input，通过当前销售属性身上的 inputVisible 来控制
            // console.log(row)    // 当前销售属性身上是没有 inputVisible 这个字段的
            // row.inputVisible = true      // 直接加上这个字段，不会从button变为input
            // 需要用响应式写      意思是，给 row 加上一个 inputVisible 属性，属性值为 true
            this.$set(row,'inputVisible',true)
            // 给row增加一个响应式数据inputValue，用来收集与展示新增的销售属性值
            this.$set(row,'inputValue','')
            this.$nextTick(() => {
                this.$refs.saveTagInput.focus()
            })
        },
        // 销售属性值当中的input框失去焦点时触发
        handleInputConfirm(row) {
            // console.log(row)
            // 解构出销售属性当中收集到的数据，需要用到 baseSaleAttrId 、 saleAttrValueName
            const {baseSaleAttrId,saleAttrValueName} = row
            // 属性值不能为空
            if (row.inputValue.trim() == '') {
                this.$message.error('属性值不能为空')
                return
            }
            // 属性值不能重复      如果有一个元素满足条件，则表达式返回true , 剩余的元素不会再执行检测。如果没有满足条件的元素，则返回false
            let result = row.spuSaleAttrValueList.some(item => {
                return item.saleAttrValueName == row.inputValue
            })
            // console.log('item',item.saleAttrValueName,typeof item.saleAttrValueName)
            // console.log('@@@',row.inputValue,typeof row.inputValue)
            // console.log(result)
            if (result) {       // result 为真的话，就是有重复的
                this.$message.error('属性值不能重复')
                return;
            }
            // 新增的销售属性值
            let newSaleAttrValue = {baseSaleAttrId:baseSaleAttrId,saleAttrValueName:row.inputValue}
            // 收集里面的值进行保存
            row.spuSaleAttrValueList.push(newSaleAttrValue)
            // 失焦，input框变为添加button
            row.inputVisible = false
        },
        // 删除销售属性，点击删除图标触发，直接删除一行
        deleteSaleAttr(row,index) {
            // console.log(row,index)
            this.spu.spuSaleAttrList.splice(index,1)
        },
        // 点击保存按钮
        async addOrUpdateSpu() {
            // 整理参数：需要整理照片墙的数据
            // 照片墙需要携带参数：需要携带imgName和imgUrl字段
            this.spu.spuImageList = this.spuImageList.map(item => {
                return {
                    imgName : item.imgName,
                    imgurl : (item.response && item.response.data) || item.imgUrl
                    // imgurl : item.imgUrl ? item.imgUrl : item.response.data
                }
            })
            // 发请求
            let rAOUSResult = await this.$API.spu.reqAddOrUpdateSpu(this.spu)
            // console.log(this.spu.spuImageList)
            // console.log(rAOUSResult)
            if (rAOUSResult.code == 200) {
                this.$message.success('保存成功！')
                // 跳转到展示数据页面，通知父组件，回到场景0        flag 是为了区分保存的是新增的数据还是修改的数据
                this.$emit('changeSpuFormScene', {scene:0,flag:this.spu.id?'修改':'新增'})
                // 重新获取数据，在父组件身上获取
            }
        },
        // 添加Spu   在父组件点击添加Spu按钮，此组件发请求获取：品牌和销售属性       接收父组件传过来的三级分类的id
        async addSpuData(id) {
            // console.log(id)  // id是父组件传过来的三级分类的id
            // 清除数据，每次点击添加按钮，要把之前添加的数据清除
            this.spu =  {
                category3Id:0,      // 三级分类的id
                tmId:'',             // 品牌id
                description:'',     // spu描述
                spuName:'',         // spu名称
                // 收集spu图片的信息
                spuImageList:[],
                // 平台属性与属性值
                spuSaleAttrList:[]
            }
            // 上次收集的图片也置空
            this.spuImageList = []
            // 整理数据
            this.spu.category3Id = id
            // 获取品牌信息
            let sTMLResult2 = await this.$API.spu.reqSpuTradeMarkList()
            // console.log(sTMLResult2)
            if (sTMLResult2.code == 200) {
                this.tradeMarkList = sTMLResult2.data
            } else {
                this.$message.error('获取品牌信息失败!')
            }
            // 获取平台全部销售属性
            let bSALResult2 = await this.$API.spu.reqBaseSaleAttrList()
            // console.log(bSALResult2)
            if (bSALResult2.code == 200) {
                this.spuBaseSaleAttrList = bSALResult2.data
            } else {
                this.$message.error('获取平台销售属性失败！')
            }
        }
    },
    computed:{
        // 计算出还未选择的销售属性
        unSelectSaleAttr() {
            // 整个平台属性一共有三个属性：颜色、尺码、版本   存放在 spuBaseSaleAttrList
            // 当前spu拥有的属于自己的销售属性 spu.spuSaleAttrList
            let result = this.spuBaseSaleAttrList.filter(item => {
                // console.log(item)   // item 是平台拥有的每一个属性，颜色、尺码、版本
                // every() 方法使用指定函数检测数组中的所有元素-如果数组中检测到有一个元素不满足，则整个表达式返回 false ，且剩余的元素不会再进行检测
                return this.spu.spuSaleAttrList.every(attr => {     // 颜色、版本
                    // console.log(attr)       // attr 是spu拥有的销售属性
                    // 如果平台属性里面的名字和spu拥有的名字不同就返回平台属性的名字
                    return item.name != attr.saleAttrName
                })
            })
            return result
        },
        // 控制添加销售属性按钮是否可点击
        addSaleAttrButton () {
            return this.saleAttrIdAndName == []
        }
    }
}
</script>

<style>
.el-tag + .el-tag {
    margin-left: 10px;
}
.button-new-tag {
    margin-left: 10px;
    height: 32px;
    line-height: 30px;
    padding-top: 0;
    padding-bottom: 0;
}
.input-new-tag {
    width: 90px;
    margin-left: 10px;
    vertical-align: bottom;
}
</style>
